package demo.hdz.mediacodecdecode.mainpage;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.view.Surface;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import demo.hdz.mediacodecdecode.AvcDecoder;
import demo.hdz.mediacodecdecode.Logger;
import demo.hdz.mediacodecdecode.MainActivity;
import demo.hdz.mediacodecdecode.bean.VideoSizeBean;
import demo.hdz.mediacodecdecode.customview.IVideoView;
import demo.hdz.mediacodecdecode.customview.VideoGLSurfaceView;
import demo.hdz.mediacodecdecode.customview.VideoGLTextureView;
import demo.hdz.mediacodecdecode.customview.VideoSurfaceView;
import demo.hdz.mediacodecdecode.customview.VideoTextureView;

/**
 * @author hdz
 * @date 2019/04/18
 */
public class MainPresenterImpl implements IMainPresenter {
    private static final String TAG = "MainPresenterImpl";
    private IMainView mMainView;
    private IMainModel mMainModel;
    private ExecutorService mSingleThreadPool;
    private AvcDecoder mAvcDecoder = null;
    private WeakReference<Context> mWeakReferenceContext;
    private MyHandler mHandler;

    public static final int MSG_DECODER_INIT_FAILED = 0x1101;
    public static final int MSG_DECODE_FINISH       = 0x1102;

    static class MyHandler extends Handler {
        WeakReference<MainPresenterImpl> mainPresenterWeakReference;
        MyHandler(MainPresenterImpl mainPresenter) {
            mainPresenterWeakReference = new WeakReference<>(mainPresenter);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_DECODE_FINISH:
                    mainPresenterWeakReference.get().mMainView.onDecodeFinish();
                    break;
                case MSG_DECODER_INIT_FAILED:
                    mainPresenterWeakReference.get().mMainView.onDecodeFailed();
                    break;
                default:
                    break;
            }
        }
    }

    public MainPresenterImpl(IMainView mainView, Context context) {
        mWeakReferenceContext = new WeakReference<>(context);
        this.mMainView = mainView;
        this.mMainModel = new MainModelImpl();
        mHandler = new MyHandler(this);
        mSingleThreadPool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1024), new ThreadPoolExecutor.AbortPolicy());
    }

    @Override
    public void release() {
        if (mAvcDecoder != null) {
            mAvcDecoder.close();
            mAvcDecoder = null;
        }
        if (mSingleThreadPool != null) {
            mSingleThreadPool.shutdown();
            mSingleThreadPool = null;
        }
    }

    @Override
    public boolean getVideoSize(Context context, String filePath, boolean bAssets) {
        VideoSizeBean videoSize = mMainModel.getVideoSize(context, filePath, bAssets);
        if (videoSize != null) {
            this.mMainView.onGetVideoSize(videoSize.getWidth(), videoSize.getHeight());
            return true;
        }
        return false;
    }

    @Override
    public boolean checkHwDecoder() {
        return mMainModel.checkHwDecoder();
    }

    @Override
    public void startDecode(final boolean bAssets, final String sH264File,
                            final int videoWidth, final int videoHeight, final int rotation,
                            final IVideoView videoView) {
        //开始解码
        mSingleThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                if (mAvcDecoder == null) {
                    mAvcDecoder = new AvcDecoder();
                }

                while (!videoView.isAvailable()) {}
                Surface surface = videoView.getSurface();
                videoView.setListener(mAvcDecoder);

                Logger.d(TAG+",startDecode: surface = " + surface);
                if (surface == null) {
                    sendMessage(MSG_DECODER_INIT_FAILED, "");
                    return;
                }
                if (!mAvcDecoder.init(videoWidth, videoHeight, surface, rotation)) {
                    Logger.e("AvcDecoder init failed!");
                    sendMessage(MSG_DECODER_INIT_FAILED, "");
                    return;
                }
                InputStream inFile = null;
                try {
                    if (bAssets) {
                        inFile = mWeakReferenceContext.get().getResources().getAssets().open(sH264File);
                    } else {
                        File file = new File(sH264File);
                        inFile = new FileInputStream(file);
                    }
                    //这是个死循环
                    mAvcDecoder.decodeFile(inFile);
                    inFile.close();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (inFile != null) {
                        try {
                            inFile.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    surface.release();
                }

                mAvcDecoder.close();
                mAvcDecoder = null;

                //解码完成通知UI线程
                sendMessage(MSG_DECODE_FINISH, "");
            }
        });
    }

    private void sendMessage(int what, Object obj) {
        if (mHandler != null) {
            Message msg = new Message();
            msg.what = what;
            msg.obj = obj;
            mHandler.sendMessage(msg);
        }
    }
}
